package com.shenhao.hpfa.service;

import com.shenhao.hpfa.exception.HpfaConnectException;
import com.shenhao.hpfa.model.DeviceInfo;
import com.shenhao.hpfa.model.OperateCommand;
import com.shenhao.hpfa.model.Payload;
import com.shenhao.hpfa.netty.HpfaNettyClient;
import com.shenhao.hpfa.properties.ControllerConfig;
import com.shenhao.hpfa.properties.HpfaProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
public class HpfaDeviceServiceImpl implements HpfaDeviceService {

    private final HpfaNettyClient nettyClient;

    private final HpfaProperties hpfaProperties;

    /**
     * 生成命令
     * @param bid 业务ID
     * @param t 命令内容
     * @param deviceSn 设备序列号
     * @return 负载对象
     */
    private <T> Payload<T> generateCommand(int bid, T t, String deviceSn) {
        Payload<T> payload = new Payload<>();
        payload.setBid(bid);
        payload.setMid(UUID.randomUUID().toString());
        payload.setDeviceSn(deviceSn);
        if (t != null) {
            payload.setChildren(Collections.singletonList(t));
        }
        return payload;
    }

    /**
     * 兼容旧版本的生成命令方法
     */
    private <T> Payload<T> generateCommand(int bid, T t) {
        return generateCommand(bid, t, hpfaProperties.getDefaultDeviceSn());
    }

    @Override
    public Payload<DeviceInfo> switchOn() throws Exception {
        return switchOn(hpfaProperties.getDefaultDeviceSn());
    }

    @Override
    public Payload<DeviceInfo> switchOff() throws Exception {
        return switchOff(hpfaProperties.getDefaultDeviceSn());
    }

    @Override
    public Payload<DeviceInfo> queryStatus() throws Exception {
        return queryStatus(hpfaProperties.getDefaultDeviceSn());
    }

    @Override
    public Payload<DeviceInfo> switchOn(String deviceSn) throws Exception {
        checkStatus(deviceSn);
        ControllerConfig config = hpfaProperties.getController(deviceSn);
        if (config == null) {
            throw new HpfaConnectException("控制器 " + deviceSn + " 不存在");
        }
        OperateCommand command = new OperateCommand();
        command.setClientId(config.getDeviceSn());
        command.setOperation(1);
        Payload<?> payload = generateCommand(202, command, config.getDeviceSn());
        return nettyClient.sendAndGetResp(deviceSn, payload, DeviceInfo.class);
    }

    @Override
    public Payload<DeviceInfo> switchOnAll() throws Exception {
        Payload<DeviceInfo> p = new Payload<>();
        for (ControllerConfig config : hpfaProperties.getControllerMap().values()) {
            OperateCommand command = new OperateCommand();
            String deviceSn = config.getDeviceSn();
            command.setClientId(deviceSn);
            command.setOperation(1);
            Payload<?> payload = generateCommand(202, command, deviceSn);
            p = nettyClient.sendAndGetResp(deviceSn, payload, DeviceInfo.class);
        }
        return p;
    }

    @Override
    public Payload<DeviceInfo> switchOffAll() throws Exception {
        Payload<DeviceInfo> p = new Payload<>();
        for (ControllerConfig config : hpfaProperties.getControllerMap().values()) {
            OperateCommand command = new OperateCommand();
            String deviceSn = config.getDeviceSn();
            command.setClientId(deviceSn);
            command.setOperation(2);
            Payload<?> payload = generateCommand(202, command, deviceSn);
            p = nettyClient.sendAndGetResp(deviceSn, payload, DeviceInfo.class);
        }
        return p;
    }

    @Override
    public Payload<DeviceInfo> switchOff(String deviceSn) throws Exception {
        checkStatus(deviceSn);
        ControllerConfig config = hpfaProperties.getController(deviceSn);
        if (config == null) {
            throw new HpfaConnectException("控制器 " + deviceSn + " 不存在");
        }

        OperateCommand command = new OperateCommand();
        command.setClientId(config.getDeviceSn());
        command.setOperation(2);
        Payload<?> payload = generateCommand(202, command, config.getDeviceSn());
        return nettyClient.sendAndGetResp(deviceSn, payload, DeviceInfo.class);
    }

    @Override
    public Payload<DeviceInfo> queryStatus(String deviceSn) throws Exception {
        checkStatus(deviceSn);
        ControllerConfig config = hpfaProperties.getController(deviceSn);
        if (config == null) {
            throw new HpfaConnectException("控制器 " + deviceSn + " 不存在");
        }

        OperateCommand command = new OperateCommand();
        command.setClientId(config.getDeviceSn());
        Payload<?> payload = generateCommand(208, command, config.getDeviceSn());
        return nettyClient.sendAndGetResp(deviceSn, payload, DeviceInfo.class);
    }

    /**
     * 检查指定控制器的连接状态
     * @param deviceSn 控制器 sn
     */
    private void checkStatus(String deviceSn) throws Exception {
        ControllerConfig config = hpfaProperties.getController(deviceSn);
        if (config == null || !config.isEnabled()) {
            log.info("控制器 {} 不存在或未启用", deviceSn);
            return;
        }
        if (nettyClient.getConnectState(deviceSn)) {
            log.info("控制器 {} 已连接", deviceSn);
            return;
        }
        int times = 0;
        log.info("控制器 {} 未连接，开始尝试连接", deviceSn);
        nettyClient.connect(deviceSn);
        while (times <= 3) {
            if (nettyClient.getConnectState(deviceSn)) {
                break;
            }
            log.info("等待控制器 {} 连接，第{}秒", deviceSn, times + 1);
            TimeUnit.SECONDS.sleep(1L);
            times++;
        }
        if (!nettyClient.getConnectState(deviceSn)) {
            throw new HpfaConnectException("暂时无法连接上控制器 " + deviceSn);
        }
    }

    /**
     * 兼容旧版本的检查状态方法
     */
    private void checkStatus() throws Exception {
        checkStatus(hpfaProperties.getDefaultDeviceSn());
    }
}